package com.linciping.useges.plugin.bean;

import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNamedElement;
import com.linciping.useges.plugin.util.CollectionUtil;

import java.util.List;
import java.util.Objects;

public class UsegesNode {

    private transient final UsegesNode parent;
    private transient final PsiNamedElement psiNamedElement;
    private final List<UsegesNode> childrenList;
    private final boolean canNavigate;

    public UsegesNode(UsegesNode parent, PsiNamedElement psiNamedElement, List<UsegesNode> childrenList, boolean canNavigate) {
        this.parent = parent;
        this.psiNamedElement = psiNamedElement;
        this.childrenList = childrenList;
        this.canNavigate = canNavigate;
    }

    public UsegesNode getParent() {
        return parent;
    }

    public List<UsegesNode> getChildrenList() {
        return childrenList;
    }

    public PsiNamedElement getPsiNamedElement() {
        return psiNamedElement;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UsegesNode that = (UsegesNode) o;
        if (parent == null) {
            return Objects.equals(psiNamedElement, that.psiNamedElement);
        } else {
            return Objects.equals(psiNamedElement, that.psiNamedElement) && Objects.equals(parent, that.parent);
        }
    }

    @Override
    public int hashCode() {
        return Objects.hash(psiNamedElement, parent);
    }

    private String showNote;

    @Override
    public String toString() {
        if (showNote == null) {
            StringBuilder node = new StringBuilder();
            if (psiNamedElement instanceof PsiFile) {
                String name = psiNamedElement.getName();
                if (name == null) return psiNamedElement.getClass().getName();
                String[] nameItems = name.split("\\.");
                String replace = "." + nameItems[nameItems.length - 1];
                node.append(name.replace(replace, ""));
            } else {
                node.append(psiNamedElement.getName());
            }
            node.append("   ").append("usges count: ").append(getUsegesCount());
            showNote = node.toString();
        }
        return showNote;
    }

    public boolean canNavigate() {
        if (!canNavigate) return false;
        if (psiNamedElement instanceof Navigatable) {
            Navigatable navigatable = (Navigatable) psiNamedElement;
            return navigatable.canNavigate();
        }
        return false;
    }

    private int usgesCount = -1;

    public int getUsegesCount() {
        if (usgesCount == -1) {
            if (canNavigate) {
                usgesCount = 1;
            } else {
                if (CollectionUtil.isListEmpty(childrenList)) {
                    usgesCount = 0;
                } else {
                    int count = 0;
                    for (UsegesNode node : childrenList) {
                        count += node.getUsegesCount();
                    }
                    usgesCount = count;
                }
            }
        }
        return usgesCount;
    }
}
